package main

import (
	"fmt"
	_ "gitee.com/z930255076/go-ext/config"
	_ "gitee.com/z930255076/go-ext/database"
	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gen/field"
	"gorm.io/gorm"
	"os"
	"strconv"
	"strings"
)

func main() {
	table := "types"
	modelName := "TypeModel"
	fileName := "type_model"

	UserName := os.Getenv("DB_USERNAME")
	Password := os.Getenv("DB_PASSWORD")
	Addr := os.Getenv("DB_HOST")
	Port, _ := strconv.Atoi(os.Getenv("DB_PORT"))
	Database := os.Getenv("DB_DATABASE")
	Prefix := os.Getenv("DB_PREFIX")

	// 连接数据库
	sqlConf := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", UserName, Password, Addr, Port, Database)
	db, err := gorm.Open(mysql.Open(sqlConf))
	if err != nil {
		panic("mysql连接错误:" + err.Error())
	}

	g := gen.NewGenerator(gen.Config{
		OutPath:      "models",
		ModelPkgPath: "models",
	})

	g.UseDB(db)

	genModels(g, Prefix+table, modelName, fileName)

	g.Execute()
}

func genModels(g *gen.Generator, table string, mName string, fName string) {
	// 自定义字段的数据类型
	// 统一数字类型为int64,兼容protobuf
	dataMap := map[string]func(detailType gorm.ColumnType) (dataType string){
		"tinyint":   func(detailType gorm.ColumnType) (dataType string) { return "int64" },
		"smallint":  func(detailType gorm.ColumnType) (dataType string) { return "int64" },
		"mediumint": func(detailType gorm.ColumnType) (dataType string) { return "int64" },
		"bigint":    func(detailType gorm.ColumnType) (dataType string) { return "int64" },
		"int":       func(detailType gorm.ColumnType) (dataType string) { return "int64" },
	}

	// 指定类型隐射关系
	g.WithDataTypeMap(dataMap) // 自定义模型结体字段的标签

	// 指定model名称
	g.WithModelNameStrategy(func(tableName string) (modelName string) {
		return mName
	})

	// 指定文件名称
	g.WithFileNameStrategy(func(tableName string) (fileName string) {
		return fName
	})

	// 将特定字段名的 json 标签加上`string`属性,即 MarshalJSON 时该字段由数字类型转成字符串类型
	jsonField := gen.FieldJSONTagWithNS(func(columnName string) (tagContent string) {
		toStringField := `balance, `
		if strings.Contains(toStringField, columnName) {
			return columnName + ",string"
		}
		return columnName
	})

	// 将非默认字段名的字段定义为自动时间戳和软删除字段;
	// 自动时间戳默认字段名为:`updated_at`、`created_at, 表字段数据类型为: INT 或 DATETIME
	// 软删除默认字段名为:`deleted_at`, 表字段数据类型为: DATETIME
	autoUpdateTimeField := gen.FieldGORMTag("updated_at", func(tag field.GormTag) field.GormTag {
		tag.Set("column", "updated_at")
		tag.Set("type", "int", "unsigned")
		tag.Set("autoUpdateTime")
		return tag
	})
	autoCreateTimeField := gen.FieldGORMTag("created_at", func(tag field.GormTag) field.GormTag {
		tag.Set("column", "created_at")
		tag.Set("type", "int", "unsigned")
		tag.Set("autoCreateTime")
		return tag
	})
	softDeleteField := gen.FieldType("deleted_at", "soft_delete.DeletedAt")

	// 模型自定义选项组
	fieldOpts := []gen.ModelOpt{jsonField, autoCreateTimeField, autoUpdateTimeField, softDeleteField}

	g.GenerateModel(table, fieldOpts...)
}
